package client;
import java.util.*;
import org.omg.CORBA.*;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CosNaming.*;
import lagern.*;
import lagern.FachPackage.exInvalidCount;
import lagern.FachPackage.exNotEnoughPieces;
import lagern.LagerPackage.exAlreadyExists;
import lagern.LagerPackage.exNotFound;


/**
 * Client class
 * @author Laurine and Vincent
 *
 */
public class Client {
	
	private static Lager lagerRef;
	private static ORB orb;
	
	public static void main (String args[]) {
		try {
			//args[0] = host
			//args[1] = port
			Integer.parseInt(args[1]);//to make sure the port is an Integer. If not, a NumberFormatException is thrown
			Properties props = new Properties();
			props.put("org.omg.CORBA.ORBInitialPort", args[1]);
			props.put("org.omg.CORBA.ORBInitialHost",args[0]);
			orb = ORB.init(args,props);
			System.out.println("ORB initialized.");
			
			//get the NamingContext	
			NamingContextExt nc = NamingContextExtHelper.narrow(
					orb.resolve_initial_references("NameService"));
			
			//Get the reference from the name "lager"
            lagerRef = LagerHelper.narrow(
                    nc.resolve_str("lager"));
            
            Scanner sc = new Scanner(System.in);
            System.out.println("What do you want to do? Write \"help\" if you need");
            while(true)
            {
            	String text = sc.nextLine();
            	checkText(text);
            }
			
			
		}catch(NumberFormatException e){
			System.err.println("Please check the port");
		}
		catch(Exception e){
			System.err.println("Problem with the connexion. Please check the parameters");
			System.err.println("<Corba Name Service host> <Corba Name Service port>");
			
		}
	}

	/**
	 * To check the text typing in by the user and to call the right method
	 * @param text The text which was typing by the user
	 */
	private static void checkText(String text) {
		if(text.equals("help"))
		{
			System.out.println("List of the possible commands:");
			System.out.println("\t<namensdienst> <lagername> quit");
			System.out.println("\t<namensdienst> <lagername> liste");
			System.out.println("\t<namensdienst> <lagername> neu <lagerfachname>");
			System.out.println("\t<namensdienst> <lagername> einlagern <lagerfachname> <anzahl>");
			System.out.println("\t<namensdienst> <lagername> auslagern <lagerfachname> <anzahl>");
		}
		else
		{
			String regExp = "[a-zA-Z]+ [a-zA-Z]+ [a-zA-Z]+( [a-zA-Z]+)?( -?[1-9]+)?";
			if(text.matches(regExp))
			{
				//to get all the parameters
				String[] arguments = text.split(" ");
				String nameService = arguments[0];
				String lagername = arguments[1];
				String function = arguments[2];
				String lagerfachname;
				try {
					//get the NamingContext	(to check if the Name Service was correctly typing.
					//If not, an InvalidName exception is thrown
					NamingContextExtHelper.narrow(
							orb.resolve_initial_references(nameService));
					if(function.equals("quit"))
					{
						//the user wants to quit
						lagerRef.quit();
						System.exit(1);
					}
					else if(function.equals("liste"))
					{
						//the user wants a list of the Lager
						System.out.println("You want a list");
						Fach[] returnedList;
						returnedList=lagerRef.holeLagerListe();
						display(returnedList);
					}
					else if(function.equals("neu"))
					{
						//the user wants to create a new lagerfach
						lagerfachname = arguments[3];
						try{
							lagerRef.neu(lagername, lagerfachname);
							System.out.println("Creation succeeded");
						}catch(exAlreadyExists e){
							System.err.println("A storage compartment with the name " + lagerfachname + 
									" already exists");
						}
					}
					else if(function.equals("einlagern"))
					{
						//the user wants to store 
						lagerfachname = arguments[3];
						String anzahl = arguments[4];
						Fach refFach;
						try {
							//get the reference of the lager
							refFach=lagerRef.hole(lagername, lagerfachname);
							//call the remote method einlagern
							refFach.einlagern(lagername, Integer.parseInt(anzahl));
							System.out.println("You have stored " + anzahl + " parts");
							
						} catch (exNotFound e) {
							System.err.println("Fach not found");
						} catch (exInvalidCount e) {
							System.err.println("Please check the number you taped in. It must be higher than 0");
						} catch (Exception e){
							System.err.println("Check the connection with the server");
						}
						
						
					}
					else if(function.equals("auslagern"))
					{
						lagerfachname = arguments[3];
						String anzahl = arguments[4];
						Fach refFach;
						try {
							//get the reference of the lager
							refFach=lagerRef.hole(lagername, lagerfachname);
							//call the remote method auslagern
							refFach.auslagern(lagername, Integer.parseInt(anzahl));
							System.out.println("You have removed " + anzahl + " parts from storage");
						} catch (exNotFound e) {
							System.err.println("The Fach with the name " + lagerfachname + " was not found");
						} catch (NumberFormatException e) {
							System.err.println("Check the anzahl, it can only have numbers");
						} catch (exInvalidCount e) {
							System.err.println("Anzahl must be higher than 0");
						} catch (exNotEnoughPieces e) {
							System.err.println("There are not enough parts on the Fach");
						}catch (Exception e){
							System.err.println("Check the connection with the server");
						}
					}
					else
					{
						System.err.println("Unknown function");
					}
				} catch (InvalidName e) {
					System.err.println("Please retype the namensdienst name");
				}
				
				
			}
			else
			{
				System.err.println("unknown command");
			}
		}
		
	}
	
	private static void Test(){
		String lagername = "lager1";
		String lagerfachname ="fach1";
		
		int anzahl = 5;
		Fach refFach;
		try{
			lagerRef.neu(lagername, lagerfachname);
			
			//get the reference of the lager
			refFach=lagerRef.hole(lagername, lagerfachname);
			
			//storage
			for(int i=0;i<5000;i++){
			refFach.einlagern(lagername, anzahl);
			}
			System.out.println("You have stored " + 5000*anzahl + " parts");
			for(int i=0;i<5000;i++){
			refFach.auslagern(lagername, anzahl);
			}
			System.out.println("You have removed " + 5000*anzahl + " parts from storage");
			
		}catch(exAlreadyExists e){
			System.err.println("A storage compartment with the name " + lagerfachname + 
					" already exists");
		}catch (exNotFound e) {
			System.err.println("Fach not found");
		}catch (NumberFormatException e) {
			System.err.println(e.toString());
		}catch (exInvalidCount e) {
			System.err.println(e.toString());
		} catch (exNotEnoughPieces e) {
			System.err.println("There are not enough parts on the Fach");
		}catch (Exception e){
			System.err.println("Check the connection with the server");
			
		}
	}


	/**
	 * To display the list of Fach sent by the server
	 * @param returnedList the list of Fach to display
	 */
	private static void display(Fach[] returnedList) {
		int i=0;
		for(Fach fach: returnedList)
		{
			if(fach != null)
			{
				i++;
				System.out.println("\t" + i + ". Name: " + fach.name() + " - " + fach.anzahl() + " parts");
			}
			else
				break;
		}
		
	}

}
